home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_10_01 / cmenu.exe / RMENU2.C < prev    next >
Text File  |  1991-11-12  |  8KB  |  368 lines

  1. /************************************************************
  2.  *    Program: RMENU Menu Interpreter
  3.  *  Module: rmenu2.c
  4.  *    Top-level menu processing
  5.  *    Written by: Leor Zolman, 7/91
  6.  ************************************************************/
  7.  
  8. #include "cmenu.h"
  9. #include "rcmenu.h"
  10.  
  11. #include <ctype.h>
  12.  
  13.  
  14. /************************************************************
  15.  * sub_menu(): 
  16.  *    Run a local menu at the given nesting level
  17.  *    Default command/menu path is supplied via "path".
  18.  ************************************************************/
  19.  
  20. int sub_menu(mnum, path)
  21. int mnum;
  22. char *path;
  23. {
  24.     MENU2 *M2p = LMenus[nestlev].Menus[mnum];
  25.     MENU *Mp = &M2p -> Menu;
  26.     char newpath[MAX_PATH];
  27.     
  28.     int cur_item = 0;
  29.     int sel_val = 0;
  30.     int factor;
  31.     
  32.     draw_menu(M2p, cur_item);        /* display the menu        */
  33.  
  34.     strcpy(newpath, make_path(path, Mp -> path));
  35.  
  36.     while (1)
  37.     {
  38.         switch (get_cmd(Mp -> nitems, cur_item, &sel_val))
  39.         {
  40.             case  KEY_UP:
  41.                 draw_item(M2p, cur_item, NORMAL, NO);
  42.                 cur_item = cur_item ? cur_item - 1 :
  43.                         Mp -> nitems - 1;
  44.                 draw_item(M2p, cur_item, STANDOUT, YES);
  45.                 break;
  46.                 
  47.             case KEY_DOWN:
  48.                 draw_item(M2p, cur_item, NORMAL, NO);
  49.                 cur_item = (cur_item == Mp -> nitems - 1) ? 0 :
  50.                         cur_item + 1;
  51.                 draw_item(M2p, cur_item, STANDOUT, YES);
  52.                 break;
  53.  
  54.             case KEY_RIGHT:
  55.                 if (Mp -> columns == 1)
  56.                     break;
  57.  
  58.                 draw_item(M2p, cur_item, NORMAL, NO);
  59.  
  60.                 factor = MAX_IROWS / Mp -> spacing;
  61.                 if (cur_item + factor < Mp -> nitems)
  62.                     cur_item += factor;
  63.                 else
  64.                     cur_item %= factor;
  65.  
  66.                 draw_item(M2p, cur_item, STANDOUT, YES);
  67.                 break;
  68.                 
  69.             case KEY_LEFT:
  70.                 if (Mp -> columns == 1)
  71.                     break;
  72.                 draw_item(M2p, cur_item, NORMAL, NO);
  73.  
  74.                 factor = MAX_IROWS / Mp -> spacing;
  75.                 if (cur_item >= factor)
  76.                     cur_item -= factor;
  77.                 else
  78.                     while (cur_item + factor < Mp -> nitems)
  79.                         cur_item += factor;
  80.  
  81.                 draw_item(M2p, cur_item, STANDOUT, YES);
  82.                 break;
  83.                 
  84.             case KEY_RUN:
  85.                 if (M2p -> Items[cur_item] -> acttyp == ACT_EXIT)
  86.                     return OK;
  87.                 if (do_item(M2p, cur_item, newpath) == EXITALL)
  88.                     return EXITALL;
  89.  
  90.                 switch(M2p -> Items[cur_item] -> nextcode)
  91.                 {
  92.                     case NXT_FIRST:
  93.                         cur_item = 0;
  94.                         break;
  95.                         
  96.                     case NXT_LAST:
  97.                         cur_item = M2p -> Menu.nitems - 1;
  98.                         break;
  99.                     
  100.                     case NXT_NEXT:
  101.                         if (cur_item < M2p -> Menu.nitems - 1)
  102.                             cur_item++;
  103.                         break;
  104.                         
  105.                     case NXT_DIRECT:
  106.                         cur_item = M2p -> Items[cur_item] -> nextitem;
  107.                         break;
  108.                 }
  109.  
  110.                 draw_menu(M2p, cur_item);   /* redisplay menu */
  111.                 break;
  112.                 
  113.             case K_DIRECT:
  114.                 if ((sel_val - 1) != cur_item)
  115.                 {
  116.                     draw_item(M2p, cur_item, NORMAL, NO);
  117.                     cur_item = sel_val - 1;
  118.                     draw_item(M2p, cur_item, STANDOUT, YES);
  119.                 }
  120.                 break;
  121.  
  122.             case K_SHELL:
  123.                 if (M2p -> Menu.escape == YES ||
  124.                   (M2p -> Menu.escape == DEFAULT && DEF_ESCAPE == YES))
  125.                 {
  126. #if SHELL_PROMPT
  127.                     if (put_msg(0, SH_PROMPT_STR) == ESC)
  128.                         break;
  129. #else
  130.                     move(ERR_ROW, 0);
  131.                     standout();
  132.                     addstr("Invoking shell. . .");
  133.                     standend();
  134. #endif
  135.  
  136.                     pre_shell();        /* set up for shell call    */
  137.                     system(SHELL_ESC);    /* run a shell                */
  138.                     post_shell();        /* restore everything        */
  139.  
  140.                     draw_menu(M2p, cur_item);
  141.                 }
  142.                 else
  143.                   put_msg(1, "Sorry, shell escapes are disabled.");
  144.                 break;
  145.  
  146.             case K_EXIT:
  147.                 return OK;
  148.  
  149.             case K_EXITALL:
  150.                 return EXITALL;
  151.  
  152.             case K_VERSION:
  153.                 put_msg(0, " RMENU Menu Interpreter v%s ",
  154.                              VERSION);
  155.                 break;
  156.  
  157.             case K_UNKNOWN:
  158.                 beep();
  159.         }
  160.         refresh();
  161.     }
  162. }
  163.  
  164.  
  165. /************************************************************
  166.  * draw_menu(): 
  167.  *    Display the entire menu, including all prompts,
  168.  *    and titles and help text (if any) for current item
  169.  *    on the screen.
  170.  ************************************************************/
  171.  
  172. Void draw_menu(M2p, curr)
  173. MENU2 *M2p;
  174. int curr;
  175. {
  176.     MENU *Mp = &M2p -> Menu;
  177.     int title_len = strlen(Mp -> title);
  178.     int i, j; 
  179.     
  180.     clear();
  181.  
  182.     move(TITLE_ROW, (SCREEN_COLS - title_len)/2);
  183.     addstr(Mp -> title);    /* Put up menu title */
  184.  
  185.     for (i = 0; i < Mp -> nitems; i++)
  186.         if (i == curr)
  187.             draw_item(M2p, i, STANDOUT, YES);
  188.         else
  189.             draw_item(M2p, i, NORMAL, NO);
  190.  
  191.     move(PROMPT_ROW, 0);
  192.     addstr(MENU_OPTS);
  193.     if (Mp -> escape == YES ||
  194.             (Mp -> escape == DEFAULT && DEF_ESCAPE == YES))
  195.         addstr(MENU_SHELL);
  196.     addstr(MENU_PROMPT);
  197.     getyx(stdscr, echoy, echox);    /* save coords of item # echo area */
  198.         
  199.     refresh();    /* display the window */
  200.  
  201. }
  202.  
  203.  
  204. /************************************************************
  205.  * draw_item():
  206.  *    Display a single item (the current item) of the
  207.  *    specified menu, using the specified video mode.
  208.  *    Display assiciated help text only if "dohelp"
  209.  *    is TRUE.
  210.  ************************************************************/
  211.  
  212. Void draw_item(M2p, item, vid_mode, dohelp)
  213. MENU2 *M2p;
  214. int item, vid_mode, dohelp;
  215. {
  216.     ITEM *Ip = M2p -> Items[item];
  217.     COORDS *Cp = &M2p -> coords[item];
  218.     int j;
  219.  
  220.     move (Cp->ypos, Cp->xpos);
  221.     printw("%2d.", item + 1);
  222.  
  223.     if (vid_mode == STANDOUT)
  224.         standout();
  225.  
  226.     printw(" %s", Ip -> text);
  227.  
  228.     for (j = 0; j < Cp -> spaces_needed; j++)
  229.             addch(' ');
  230.  
  231.     if (vid_mode == STANDOUT)
  232.         standend();
  233.  
  234.     if (dohelp == YES)
  235.     {
  236.         move(HELP_ROW0, HELP_COL0);
  237.  
  238.         if (*Ip -> help)
  239.         {
  240.             addstr(" HELP: ");    /* display help text    */
  241.             standout();
  242.             move (HELP_ROW, (80 - strlen(Ip -> help))/2);
  243.             addstr(Ip -> help);
  244.             standend();
  245.         }
  246.         else
  247.         {
  248.             addstr("       ");    /* clear help text area    */
  249.             move(HELP_ROW, 0);
  250.         }
  251.  
  252.         clrtoeol();
  253.     }
  254. }
  255.  
  256.  
  257. /************************************************************
  258.  * get_cmd()
  259.  *    Get a command from the user.
  260.  *    Arrow keys or space returns the appropriate K_ code.
  261.  *    Pressing Enter returns the K_RUN code.
  262.  *    Pressing ! returns the K_SHELL code.
  263.  *    Entering a direct number returns K_DIRECT,
  264.  *    and the sel_val is set (indirectly) to selection number
  265.  *  (1-based).
  266.  ************************************************************/
  267.  
  268. int get_cmd(nitems, curr, sel_val)
  269. int nitems;
  270. int curr;
  271. int *sel_val;
  272. {
  273.     int ch;
  274.     int newval;
  275.     int savy, savx;
  276.  
  277.     static int digits = FALSE;    /* true if digits being entered */
  278.     
  279.     move(echoy, echox);    /* move to prompt location */
  280.     printw("%d", curr + 1);
  281.     getyx(stdscr, savy, savx);
  282.     clrtoeol();
  283.     move(savy, savx);
  284.     refresh();
  285.     
  286.     while (1)
  287.     {
  288.         ch = getch();
  289.         if (!isdigit(ch))
  290.             digits = FALSE;
  291.         switch (ch)
  292.         {
  293.             case KEY_UP:
  294.             case '\b':        /* WYSE 60s send this for left arrow */
  295.                 clrtoeol();
  296.                 return KEY_UP;
  297.  
  298.             case ' ':
  299.             case KEY_DOWN:
  300. #if UNIX || XENIX
  301.             case '\n':        /* WYSE 60s send this for down arrow */
  302. #endif
  303.                 clrtoeol();
  304.                 return KEY_DOWN;
  305.  
  306.             case KEY_RIGHT:
  307.                 return KEY_RIGHT;
  308.  
  309.             case KEY_LEFT:
  310.                 return KEY_LEFT;
  311.  
  312.             case KEY_RUN:
  313.                 return KEY_RUN;
  314.  
  315.             case 'e':
  316.             case 'E':
  317.                 return K_EXIT;
  318.  
  319.             case 'x':
  320.             case 'X':
  321.                 return K_EXITALL;
  322.                 
  323.             case 'v':
  324.             case 'V':
  325.                 return K_VERSION;
  326.  
  327.             case '!':
  328.                 return K_SHELL;
  329.  
  330.             case ESC:        /* clear digits area */
  331.                 digits = FALSE;
  332.                 move(echoy, echox);    
  333.                 clrtoeol();
  334.                 refresh();
  335.                 break;
  336.                 
  337.             default:        /* handle digits */
  338.                 if (!isdigit(ch))
  339.                     return K_UNKNOWN;
  340.  
  341.                 if (digits && 
  342.                     (newval = *sel_val * 10 + (ch - '0')) <= nitems
  343.                         && newval > 0)
  344.                 {
  345.                     addch(ch);
  346.                     refresh();
  347.                     *sel_val = newval;
  348.                     return K_DIRECT;
  349.                 }
  350.                 else if ( (newval = ch - '0') && newval <= nitems)
  351.                 {
  352.                     digits = TRUE;
  353.                     move(echoy, echox);    
  354.                     addch(ch);
  355.                     clrtoeol();
  356.                     refresh();
  357.                     *sel_val = newval;
  358.                     return K_DIRECT;
  359.                 }
  360.                 else
  361.                 {
  362.                     digits = FALSE;
  363.                     beep();
  364.                 }
  365.         }
  366.     }
  367. }
  368.